import { AxiosPromise, AxiosRequestConfig, AxiosResponse } from "../types";
import { parseHeaders } from "../helpers/headers";
export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    const {
      url,
      method = "GET",
      data = null,
      headers,
      timeout,
      withCredentials,
      responseType,
    } = config;

    const xhr = new XMLHttpRequest();

    xhr.open(method.toUpperCase(), url, true);

    if (responseType) {
      xhr.responseType = responseType;
    }

    if (timeout) {
      xhr.timeout = timeout;
    }

    if (withCredentials) {
      xhr.withCredentials = withCredentials;
    }

    if (headers) {
      Object.keys(headers).forEach((key) => {
        xhr.setRequestHeader(key, headers[key]);
      });
    }

    xhr.ontimeout = () =>
      reject(new Error(`Timeout of ${timeout} ms exceeded`));
    xhr.onerror = () => reject(new Error("Network Error"));

    xhr.onreadystatechange = () => {
      // 0 1 2 3 4
      if (xhr.readyState !== 4) {
        return;
      }
      // 超时和报错
      if (xhr.status === 0) {
        return;
      }
      const responseHeaders = parseHeaders(xhr.getAllResponseHeaders());
      const responseData =
        responseType === "text" ? xhr.responseText : xhr.response;
      const response: AxiosResponse = {
        data: responseData,
        status: xhr.status,
        statusText: xhr.statusText,
        headers: responseHeaders,
        config,
        request: xhr,
      };
      handleResponse(response);
    };

    xhr.send(data); //支持格式有text, arraybuffer, blob, document, formdata

    const handleResponse = (response: AxiosResponse) => {
      if (response.status >= 200 && response.status < 304) {
        resolve(response);
      } else {
        reject(new Error("Request failed with status code " + response.status));
      }
    };
  });
}
